﻿using FreesenseSubAIS.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using FreesenseSubAIS.InspProcess;
using NLog;
using Exception = System.Exception;
using FreesenseSubAIS.ImageProcess;
using ExternControlModel;

namespace FreesenseSubAIS
{
    internal class InspEntity
    {
        private IStrategy _strategy;
        private int _progress = 0;//进度
        private static readonly InspEntity _intance = new InspEntity();
        private static readonly ILogger _log = LogManager.GetCurrentClassLogger();
        private ItemResult ele_ready;
        internal ResultInfo InspResult;//检测总结果
        internal APICommand InspLogic = null;//检测逻辑
        /// <summary>
        /// 触发msg消息事件，index为事件索引
        /// 0-开始检测，产品ID
        /// 1-切换型号，产品型号
        /// 2-检测结果显示，结果
        /// 3-检测过程，过程
        /// </summary>
        internal event Action<string, int> MsgEvent;
        /// <summary>
        /// 结果回馈事件
        /// </summary>
        internal event Action<bool, string> BackResultEvent;
        /// <summary>
        /// 返回当前进度事件
        /// </summary>
        internal event Action<int> ChangValue;
        /// <summary>
        /// 进度值
        /// </summary>
        internal int ProgressValue
        {
            get { return _progress; }
            set
            {
                _progress = value;
                ChangValue?.Invoke(_progress);
            }
        }

        internal static string Msg;
        internal static int InspState;
        internal static InspEntity Intance
        {
            get { return _intance; }
        }
        #region 构造
        public InspEntity()
        {
            //InspLogic = ParamAnalysis.AnalysisParam(Device.defaultProduct);
            _strategy = new Strategy0085();
        }
        #endregion 构造

        #region 查询定位结果、检测结果、切图数量
        public void SetterInterface(IExternControlAdapter<ResultInfo> externcmd)
        {
            externcmd.StartTask += Start;
            externcmd.RequestDust += QueryPara;
            externcmd.RequestVisiual += QueryPara;
            externcmd.RequestFrame += QueryPara;
            externcmd.BackResult += Externcmd_BackResult;
            externcmd.ChangeOver += Externcmd_ChangeOver; ;
        }

        private bool Externcmd_ChangeOver(string product)
        {
            var result = false;
            var ori = Device.Parameter.DefaultProductId;
            try
            {
                Device.Parameter.DefaultProductId = product;
                GetProjectConfig();
                if (Device.defaultProduct != null && Device.CorrectIndex > 0)
                {
                    if (MsgEvent != null)
                        MsgEvent("换型成功", 1);
                    result = true;
                }
            }
            catch
            {
                Device.Parameter.DefaultProductId = ori;
                GetProjectConfig();
                if (MsgEvent != null)
                    MsgEvent("换型失败", 1);
                result = false;
            }
            return result;
        }

        private ResultInfo Externcmd_BackResult()
        {
            return InspResult;
        }

        #endregion 查询定位结果、检测结果、切图数量

        #region 存储检测方案到文件
        internal void WriteFile()
        {
            Utiles.SerializeToXml("ConfigurationInfo.xml", InspLogic);
        }
        internal void ReadFile()
        {
            InspLogic = Utiles.DeserializeFromXml<APICommand>("ConfigurationInfo.xml");
        }
        #endregion 存储检测方案到文件

        #region 接收外部指令
        private void Start(string id)
        {
            try
            {
                _log.Info("接收到检测任务");
                _strategy.ProcessStart(id);
                if (MsgEvent != null)
                    MsgEvent(id, 0);
                ProgressValue = 0;
                Msg = "待定位";
                ele_ready = ItemResult.none;
                Task.Factory.StartNew(() => QueryResult(), TaskCreationOptions.AttachedToParent);
            }
            catch (Exception ex)
            {
                _log.Error("InspEntity.Start()异常" + ex.Message);
            }
        }

        private void ElectricStart()
        {
            Task.Factory.StartNew(() =>
            {
                try
                {
                    if (InspLogic.Poweron != null && InspLogic.Poweron.Count > 0)
                    {
                        InspLogic.Poweron.ForEach(x => QueryPara((int)x.Picindex));
                    }
                    if (!Device.DitUseVirtual.All(x => x.Value))
                    {
                        _strategy.ProcessFinished();
                        MsgEvent?.Invoke("光学环境结束完成",3);
                    }
                    Msg = "图片采集完成，等待算法处理结果...";
                }
                catch (Exception ex)
                {
                    _log.Error("电测图指令执行出错{0}", ex.Message);
                }
            });
        }

        private void Finished(bool result, string ipprot)
        {
            _strategy.ProcessFinished();
            if (BackResultEvent != null)
                BackResultEvent(result, ipprot);
        }

        private bool ChangeProduct(string productid)
        {
            Device.ICEconnection = true;
            var msg = "";
            var result = true;
            if (Device.defaultProduct.ProductName == productid && Device.defaultProduct.ParamList.Count > 0)
                msg = "Host:切换型号成功" + Device.Parameter.DefaultProductId;
            else
            {
                Device.Parameter.DefaultProductId = productid;
                GetProjectConfig();
                if (Device.defaultProduct != null && Device.defaultProduct.ParamList.Count > 0)
                {
                    Device.SaveParameter();
                    msg = string.Format("Host:切换型号成功{0}", Device.Parameter.DefaultProductId);
                }
                else
                {
                    result = false;
                    msg = "Host:切换型号失败-" + productid;
                }
            }
            if (MsgEvent != null)
                MsgEvent(msg, 1);
            return result;
        }

        public void GetProjectConfig()
        {
            try
            {
                Device.defaultProduct = ProductManager.OpenProduct(Device.Parameter.DefaultProductId);
                if (Device.Parameter.SubNetInfo != null)
                    Device.SubID = Device.Parameter.SubNetInfo.LocalIP + Device.Parameter.SubNetInfo.MacAddr;
                InspLogic = ParamAnalysis.AnalysisParam(Device.defaultProduct);
                ImageManage.Instance.Refrush(1);
                var item = Device.defaultProduct.ParamList.Find(x => x.InspGroup[0].InspMethods.Intersect(Device.CorrectArray).Any());
                Device.CorrectIndex = item.PicParameter.Picindex;
                Device.InspRecordCount = Device.defaultProduct.ParamList.Count(x => x.InspGroup[0].InspMethods.Any());
                if (item.InspGroup[0].InspMethods.Count > 1)//矫正图需要检测
                    Device.InspRecordCount += 1;
            }
            catch (System.Exception ex)
            {
                throw new ArgumentException("GetProjectConfig()异常：" + ex.TargetSite + ex.Message);
            }
        }
        #endregion 接收外部指令

        /// <summary>
        /// 检测电测项
        /// </summary>
        /// <param name="index"></param>
        private void QueryPara(int index)
        {
            try
            {
                if (!Msg.Contains("结束"))
                    Msg = string.Format("正在检测图：{0}", index);
                var s = Device.defaultProduct.ParamList.Find(x => x.PicParameter.Picindex == index);
                if (s == null)
                    throw new ArgumentException("当前型号未匹配到对应的图片序号:" + index);
                InspState = index;
                if (!Device.DitUseVirtual.All(x => x.Value))
                {
                    _strategy.ItemTaskBefore(s.PicParameter);
                    MsgEvent?.Invoke(string.Format("{0} 光学环境准备完毕", s.PicParameter.Picname), 3);
                }
                var shot = Excuteshot(s);
                MsgEvent?.Invoke(string.Format("执行完 {0} 拍图，{1}超时", s.PicParameter.Picname, shot ? "未" : "已"), 3);
                ProgressValue++;
                if (!Device.DitUseVirtual.All(x => x.Value))
                    _strategy.ItemTaskFinished(s.PicParameter);
            }
            catch (System.Exception ex)
            {
                throw new IndexOutOfRangeException(ex.Message);
            }
        }

        /// <summary>
        /// 自动执行检测
        /// </summary>
        /// <exception cref="ArgumentException"></exception>
        internal void ExcuteCmd()
        {
            try
            {
                Start(DateTime.Now.ToString("yyyyMMdd-HHmmss"));
                ExcuteVisualAuto();
                ExcuteEleAuto();
            }
            catch (System.Exception ex)
            {
                throw new ArgumentException(message: ex.ToString());
            }
        }


        private bool Excuteshot(AlgParameter param)
        {
            if (param.PicParameter.Picindex > -1 && param.PicParameter.Picindex < Device.defaultProduct.ParamList.Count)
            {
                if (!param.InspGroup.Any(x => x.InspMethods.Any()))//不需拍图
                    return true;
            }
            ImageManage.Instance.SetCmd(param.InspGroup.Select(x => x.CameraName).ToArray());
            ImageManage.Instance.SetExposureTime(param.InspGroup.Select(x => x.CameraName).ToArray(), param.InspGroup.Select(x => x.ExproseTime).ToArray());
            ImageManage.Instance.OneShot(param.InspGroup.Select(x => x.CameraName).ToArray());
            var timeout = ImageManage.Instance.WaitPicGroup(param.PicParameter.DelayTime);
            return timeout;
        }
        /// <summary>
        /// 自动目测清灰
        /// </summary>
        /// <returns></returns>
        private bool ExcuteVisualAuto()
        {
            if (InspLogic == null)
                return false;
            if (InspLogic.Dust != null && InspLogic.Dust.Dustlist != null && InspLogic.Dust.Dustlist.Count > 0)
                InspLogic.Dust.Dustlist.ForEach(x => QueryPara((int)x.Picindex));
            if (InspLogic.Visiual != null && InspLogic.Visiual.VisEnable == 1)
            {
                QueryPara((int)InspLogic.Visiual.Picindex);
            }
            return true;
        }
        /// <summary>
        /// 自动电测
        /// </summary>
        /// <returns></returns>
        private bool ExcuteEleAuto()
        {
            bool flag = _strategy.ElectricReady();
            flag = Device.DitUseVirtual.All(x => x.Value) || flag;
            ele_ready = (flag ? ItemResult.pass : ItemResult.failed);
            bool flag2 = ele_ready.GetHashCode() == ItemResult.pass.GetHashCode();
            if (flag2)
            {
                ElectricStart();
            }
            else
            {
                _strategy.ProcessFinished();
            }
            return flag;

        }
        private bool QueryResult()
        {
            try
            {
                InspResult = new ResultInfo { result = ItemResult.none, Flagindex = 0, Sortlist = new List<int>() };
                var blnPass = false;
                var times = Device.defaultProduct.Delaytime.AllResults + 50;//清灰经验值2秒
                _log.Info("开始等待检测结果");
                var timeout = ImageManage.Instance.WaitAllTask(times);
                _log.Info(string.Format("等待检测结果完成，{0}超时", timeout ? "未" : "已"));
                if (!Device.DitUseVirtual.All(x => x.Value))//超时ETS再次断电
                    _strategy.ProcessFinished();
                blnPass = ImageManage.Instance.GetTotalResult();
                #region 回传结果信息
                MsgEvent?.Invoke(blnPass.ToString(), 2);
                #endregion
                return blnPass;
            }
            catch (Exception ex)
            {
                _log.Error("QueryResult异常：" + ex.ToString());
            }
            return false;
        }
        #region 旧版注释
        //private void QueryInspResult()
        //{
        //    InspResult = ItemResult.none;
        //    int count = InspLogic.GetNeeds() + 1;//加定位的
        //    int times = 6000;//等待两分钟
        //    Task.Run(() =>
        //        {
        //            while (times-- > 0)
        //            {
        //                if (CameraInsp.Instance.CorrectRlt.Equals(ItemResult.failed))
        //                {
        //                    InspResult = ItemResult.failed;
        //                    break;
        //                }
        //                if (CameraInsp.Instance.CorrectRlt.Equals(ItemResult.none))
        //                    continue;
        //                if (CameraInsp.Instance.Insprecord.ListResults.Count == count)
        //                {
        //                    break;
        //                }
        //                Thread.Sleep(20);
        //            }
        //            if (CameraInsp.Instance.Insprecord.ListResults.Any(x => x.Result.Equals(false)))
        //            {
        //                InspResult = ItemResult.failed;
        //                return;
        //            }
        //            else
        //                if (CameraInsp.Instance.Insprecord.ListResults.Count == count)
        //                    InspResult = ItemResult.pass;
        //        });
        //}
        #endregion
        #region formmain业务迁移

        /// <summary>
        /// 返回关键信息
        /// </summary>
        /// <returns></returns>
        //private APICmd Parperinfo(string productid)
        //{
        //    var cmd = new APICmd
        //    {
        //        Correct =
        //        {
        //            Base = Translate(InspEntity.Intance.InspLogic.Correct),
        //            CorrIndex = InspEntity.Intance.InspLogic.Correct.CorrIndex
        //        },
        //        Dust = { Dustlist = new List<PicInfo>() }
        //    };
        //    foreach (var s in InspEntity.Intance.InspLogic.Dust.Dustlist)
        //    {
        //        cmd.Dust.Dustlist.Add(new PicInfo { Delaytime = s.CorrDelaytime, Exporsetime = s.CorrExporsetime, index = s.Picindex, Intensity = s.Intensity });
        //    }
        //    if (InspEntity.Intance.InspLogic.Visiual != null)
        //    {
        //        cmd.Visiual = new VisiualPic { Base = Translate(InspEntity.Intance.InspLogic.Visiual), VisEnable = (InspEntity.Intance.InspLogic.Visiual.VisEnable == 1) };
        //    }
        //    cmd.Poweron = new List<PowerOnPic>();
        //    foreach (var s in InspEntity.Intance.InspLogic.Poweron)
        //    {
        //        cmd.Poweron.Add(new PowerOnPic { Base = Translate(s), ChangTime = s.ChangTime, NeedInsp = (s.NeedInsp == 0) });
        //    }
        //    return cmd;
        //}
        //private PicInfo Translate(BaseInfo bi)
        //{
        //    var pi = new PicInfo
        //    {
        //        Delaytime = bi.CorrDelaytime,
        //        Exporsetime = bi.CorrExporsetime,
        //        index = bi.Picindex,
        //        Intensity = bi.Intensity
        //    };
        //    return pi;
        //}
        #endregion
    }
}
